import os, sys, time
import wx
import remem

from threading import Thread

class MainForm(wx.Frame):
  def __init__(self, parent, id, title):
    super(MainForm, self).__init__(parent, title=title, size=(400, 400))

    panel = wx.Panel(self)
    sizer = wx.GridBagSizer(2, 3)

    """
    Setting up the menu bar.
    """
    edit_menu_id = wx.NewId()

    menu = wx.MenuBar()
    editMenu = wx.Menu()
    preferences = editMenu.Append(edit_menu_id, "Preferences")
    menu.Append(editMenu, "Edit")
    self.SetMenuBar(menu)

    """
    Setting up the data entry fields.
    """
    subject = wx.StaticText(panel, label="Subject")
    note = wx.StaticText(panel, label="Note")
    self.subject_panel = wx.TextCtrl(panel)
    self.note_panel = wx.TextCtrl(panel, style=wx.TE_MULTILINE)

    """
    Populating the sizer.
    """
    sizer.Add(subject, pos=(0,0), flag=wx.TOP|wx.LEFT, border=15)
    sizer.Add(note, pos=(1,0), flag=wx.LEFT, border=15)
    sizer.Add(self.subject_panel, pos=(0,1), span=(1,2),
      flag=wx.TOP|wx.RIGHT|wx.EXPAND, border=15)
    sizer.Add(self.note_panel, pos=(1,1), span=(2,2),
      flag=wx.BOTTOM|wx.RIGHT|wx.EXPAND, border=15)

    sizer.AddGrowableCol(2)
    sizer.AddGrowableRow(2)
    panel.SetSizerAndFit(sizer)

    """
    Binding data entry fields to their respective controls and functions.
    """
    index_id = wx.NewId()
    clear_id = wx.NewId()
    asearch_id = wx.NewId()
    psearch_id = wx.NewId()
    self.Bind(wx.EVT_MENU, self.onCtrlReturn, id=index_id)
    self.Bind(wx.EVT_MENU, self.onCtrlE, id=clear_id)
    self.Bind(wx.EVT_MENU, self.onCtrlF, id=asearch_id)
    self.Bind(wx.EVT_MENU, self.onCtrlG, id=psearch_id)

    self.accel = wx.AcceleratorTable([(wx.ACCEL_CTRL, 13, index_id),
                                      (wx.ACCEL_CTRL, ord('e'), clear_id),
                                      (wx.ACCEL_CTRL, ord('f'), asearch_id),
                                      (wx.ACCEL_CTRL, ord('g'), psearch_id)])
    self.SetAcceleratorTable(self.accel)
    self.Show()

  """
  Indexes text in the Note field, saving it to the directory with the name
  of the Subject field.
  """
  def onCtrlReturn(self, event):
    subject_text = str(self.subject_panel.GetValue())
    note_text = str(self.note_panel.GetValue())

    if subject_text == "":
      message = "Note temporarily saved: enter a subject and try again."
      self.note_panel.SetValue(message)
    else:
      remem.index(subject_text, note_text)
      self.note_panel.SetValue("")
      print "item indexed"

  """
  Clears the Subject and Note fields.
  """
  def onCtrlE(self, event):
    self.subject_panel.SetValue('')
    self.note_panel.SetValue('')

  """
  Open active search window.
  """
  def onCtrlF(self, event):
    frame = Search(self, 1, "Active Search")
    return True

  """
  Open passive search window
  """
  def onCtrlG(self, event):
    frame = PassiveSearch(self, 2, "Passive Search")
    return True

"""
Class for active search window
"""
class Search(MainForm, Thread):
  def __init__(self, parent, id, title):
    wx.Frame.__init__(self, parent, id, title, size=(400,400))
    Thread.__init__(self)
    self.start()

    panel = wx.Panel(self)
    sizer = wx.GridBagSizer(2, 3)

    """
    Setting up the data entry fields.
    """
    database = wx.StaticText(panel, label="Database")
    query = wx.StaticText(panel, label="Query")
    results = wx.StaticText(panel, label="Results")
    self.database_panel = wx.TextCtrl(panel)
    self.query_panel = wx.TextCtrl(panel)
    self.result_panel = wx.TextCtrl(panel, style=wx.TE_MULTILINE)

    """
    Populating the sizer.
    """
    sizer.Add(database, pos=(0,0), flag=wx.TOP|wx.LEFT, border=19)
    sizer.Add(query, pos=(1,0), flag=wx.LEFT, border=19)
    sizer.Add(results, pos=(2,0), flag=wx.LEFT, border=19)
    sizer.Add(self.database_panel, pos=(0,1), span=(1,2),
      flag=wx.TOP|wx.LEFT|wx.RIGHT|wx.EXPAND, border=15)
    sizer.Add(self.query_panel, pos=(1,1), span=(1,2),
      flag=wx.LEFT|wx.RIGHT|wx.EXPAND, border=15)
    sizer.Add(self.result_panel, pos=(2,1), span=(2,2),
      flag=wx.BOTTOM|wx.LEFT|wx.RIGHT|wx.EXPAND, border=15)

    sizer.AddGrowableCol(2)
    sizer.AddGrowableRow(2)
    panel.SetSizerAndFit(sizer)

    """
    Binding data entry fields to their respective controls and functions.
    """
    search_id = wx.NewId()
    self.Bind(wx.EVT_MENU, self.onCtrlReturn, id=search_id)

    self.accel = wx.AcceleratorTable([(wx.ACCEL_CTRL, 13, search_id)])
    self.SetAcceleratorTable(self.accel)

    self.Show()

  """
  Searches database specified in Database field with a query specified in
  Query field.
  """
  def onCtrlReturn(self, event):
    db_text = str(self.database_panel.GetValue())
    query_text = str(self.query_panel.GetValue())

    if db_text == "":
      self.result_panel.SetValue("No subject specified.")
    else:
      u_results = unicode(remem.search(db_text, query_text))
      u_results = u_results.encode()

      if len(u_results) > 0:
        self.result_panel.SetValue(u_results)
      else:
        self.result_panel.SetValue("No results found.")

"""
Class for passive search window.
"""
class PassiveSearch(MainForm, Thread):
  def __init__(self, parent, id, title):
    wx.Frame.__init__(self, parent, id, title, size=(400,400))
    Thread.__init__(self)
    self.start()

    """
    self.parent necessary to get database and query terms from the parent
    window.
    """
    self.parent = parent
    panel = wx.Panel(self)
    sizer = wx.GridBagSizer(2, 3)

    """
    Setting up data entry fields.
    """
    database = wx.StaticText(panel, label="Database")
    query = wx.StaticText(panel, label="Query")
    results = wx.StaticText(panel, label="Results")
    self.database_panel = wx.TextCtrl(panel)
    self.query_panel = wx.TextCtrl(panel)
    self.result_panel = wx.TextCtrl(panel, style=wx.TE_MULTILINE)

    """
    Populating the sizer.
    """
    sizer.Add(database, pos=(0,0), flag=wx.TOP|wx.LEFT, border=19)
    sizer.Add(query, pos=(1,0), flag=wx.LEFT, border=19)
    sizer.Add(results, pos=(2,0), flag=wx.LEFT, border=19)
    sizer.Add(self.database_panel, pos=(0,1), span=(1,2),
      flag=wx.TOP|wx.LEFT|wx.RIGHT|wx.EXPAND, border=15)
    sizer.Add(self.query_panel, pos=(1,1), span=(1,2),
      flag=wx.LEFT|wx.RIGHT|wx.EXPAND, border=15)
    sizer.Add(self.result_panel, pos=(2,1), span=(2,2),
      flag=wx.BOTTOM|wx.LEFT|wx.RIGHT|wx.EXPAND, border=15)

    sizer.AddGrowableRow(2)
    sizer.AddGrowableCol(2)
    panel.SetSizerAndFit(sizer)

    """
    Setting up the timer.
    The call to passiveSearch is bound to the timer: no user input is
    currently used to activate it, and there is currently no way to
    deactivate it without closing the window.
    """
    self.timer = wx.Timer(self)
    self.Bind(wx.EVT_TIMER, self.passiveSearch, self.timer)
    self.timer.Start(1500)
    self.Show()

  """
  Searches database specified in Database field with a query speciied in
  Query field.
  This works in such a way that passiveSearch will be called once every
  1500 milliseconds.
  """
  def passiveSearch(self, event):
    self.database_panel.SetValue(self.parent.subject_panel.GetValue())
    self.query_panel.SetValue(self.parent.note_panel.GetValue())

    db_text = str(self.database_panel.GetValue())
    query_text = str(self.query_panel.GetValue())

    if db_text == "":
      self.result_panel.SetValue("No subject specified.")
    else:
      u_results = unicode(remem.search(db_text, query_text))
      u_results = u_results.encode()

      if len(u_results) > 0:
        self.result_panel.SetValue(u_results)
      else:
        self.result_panel.SetValue("No results found")
      self.timer.Start(1500)

class Program(wx.App):
  def OnInit(self):
    frame = MainForm(None, -1, "Memory Assist")
    frame.CenterOnScreen()
    frame.Show(True)
    return True

if __name__ == '__main__':
  app = Program(0)
  app.MainLoop()
